﻿// -----------------------------------------------------------------------
// <copyright file="FileSystemTimelineDataProvider.cs" company="EPAM Systems">
////Copyright (c) EPAM Systems. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

namespace Epam.PhotoGallery.Bussines.Providers
{
	using System;
	using System.Collections.Generic;
	using System.Configuration;
	using System.Globalization;
	using System.IO;
	using System.Linq;
	using System.Security.Principal;
	using System.Xml.Linq;
	using Epam.PhotoGallery.Bussines.Configuration;
	using Epam.PhotoGallery.Interfaces.DataTransferObjects;
	using Epam.PhotoGallery.Interfaces.Providers;

	/// <summary>
	/// This class represent FileSystemTimlineData provider
	/// </summary>
	public class FileSystemTimelineDataProvider : ITimelineDataProvider
	{
		#region Private fields

		/// <summary>
		/// List<TimeItem> items
		/// </summary>
		private readonly List<TimeItem> items = new List<TimeItem>();

		#endregion

		/// <summary>
		/// Removes the domain.
		/// </summary>
		/// <param name="fullUserName">Full name of the user.</param>
		/// <returns>
		/// Return user name without sub domain string.
		/// </returns>
		public static string RemoveDomain(string fullUserName)
		{
			int x = fullUserName.IndexOf("\\");
			return fullUserName.Remove(0, x + 1);
		}

		/// <summary>
		/// Gets the available albums.
		/// </summary>
		/// <param name="rootPath">The root path.</param>
		/// <returns>
		/// Return IEnumerable<TimeItem>.
		/// </returns>
		public IEnumerable<TimeItem> GetAvailableAlbums(string rootPath)
		{
			this.FillTimeItems(rootPath);
			return this.items;
		}

		/// <summary>
		/// Gets the available cover. Not used yet
		/// </summary>
		/// <param name="rootPath">The root path.</param>
		/// <returns>
		/// Return start cover for gallery.
		/// </returns>
		public TimeItem GetCover(string rootPath)
		{
			////    //string cover = Path.Combine(rootPath, @"cover.xml");
			////    //string coverImage = Path.Combine(rootPath, @"cover.png");
			////    var item = new TimeItem
			////    {

			////        AlbumPath = rootPath,
			////        HeadLine = string.Empty,
			////        Caption = string.Empty,
			////        Description = string.Empty,
			////        Creator = string.Empty,
			////        //CoverImageSource = coverImage,
			////        Id = Guid.NewGuid()
			////    };

			////    //if (File.Exists(cover))
			////    //{
			////    //    using (StreamReader xmlStreamReader = File.OpenText(cover))
			////    //    {
			////    //        XElement element = XElement.Load(xmlStreamReader);

			////    //        item.HeadLine = GetConfigValue(element.Element("Headline")) ?? "EPAM PHOTO GALLERY";
			////    //        item.Description = GetConfigValue(element.Element("MainText")) ?? "mogilev department";
			////    //        item.CoverImageSource = GetConfigValue(element.Element("Cover")) ?? coverImage;
			////    //        //item.Asset.Creator = GetConfigValue(element.Element("Creator")) ?? point.Asset.Creator;
			////    //    }
			////    //}

			////    return item;
			return new TimeItem();
		}

		/// <summary>
		/// Gets the images for album.
		/// </summary>
		/// <param name="rootPath">The root path.</param>
		/// <returns>
		/// Return IEnumerable<GalleryImage> for current album.
		/// </returns>
		public IEnumerable<GalleryImage> GetImagesForAlbum(string rootPath)
		{
			var rootFolder = (RepositorySection)ConfigurationManager.GetSection(RepositorySection.RepositorySectionName);
			var result = new List<GalleryImage>();

			var files = Directory.GetFiles(rootPath).Where(f => f.ToLower().EndsWith(".jpeg") || f.ToLower().EndsWith(".jpg"));

			foreach (var item in files)
			{
				result.Add(new GalleryImage
				{
					Path = item,
					Name = Path.GetFileNameWithoutExtension(item),
					Id = Guid.NewGuid()
				});
			}
			return result;
		}

		/// <summary>
		/// Gets the configuration value.
		/// </summary>
		/// <param name="element">The element.</param>
		/// <returns>
		/// Return XML element in string.
		/// </returns>
		private static string GetConfigValue(XElement element)
		{
			return element != null ? element.Value : null;
		}

		/// <summary>
		/// Gets the file owner.
		/// </summary>
		/// <param name="fileName">Name of the file.</param>
		/// <returns>
		/// Return file owner in string.
		/// </returns>
		private static string GetFileOwner(string fileName)
		{
			var result = string.Empty;
			var fs = File.GetAccessControl(fileName);

			var sid = fs.GetOwner(typeof(SecurityIdentifier));
			try
			{
				result = sid.Translate(typeof(NTAccount)).Value;
			}
			catch (IdentityNotMappedException)
			{
				result = "Outsider";
			}
			return result;
		}

		/// <summary>
		/// Fills the time items.
		/// </summary>
		/// <param name="currentDirectorypath">The current directory path.</param>
		private void FillTimeItems(string currentDirectorypath)
		{
			var currentDirectory = Directory.GetDirectories(currentDirectorypath);

			foreach (string directory in currentDirectory)
			{
				this.FillTimeItems(directory);
			}

			var files = Directory.GetFiles(currentDirectorypath).Where(f => f.ToLower().EndsWith(".jpeg") || f.ToLower().EndsWith(".jpg"));

			if (files.Any())
			{
				string viewer = Path.Combine(currentDirectorypath, @"viewer.xml");

				var point = new TimeItem
				{
					AlbumPath = currentDirectorypath,
					HeadLine = Path.GetFileName(currentDirectorypath),
					Caption = string.Empty,
					Description = string.Empty,
					CoverImageSource = files.First(),
					Id = Guid.NewGuid()
				};

				point.Creator = RemoveDomain(GetFileOwner(files.First()));
				point.StartDate = File.GetLastWriteTime(point.CoverImageSource);

				if (File.Exists(viewer))
				{
					using (StreamReader xmlStreamReader = File.OpenText(viewer))
					{
						XElement element = XElement.Load(xmlStreamReader);

						point.HeadLine = GetConfigValue(element.Element("Headline")) ?? point.HeadLine;
						point.Description = GetConfigValue(element.Element("MainText")) ?? point.Description;
						point.CoverImageSource = GetConfigValue(element.Element("Cover")) ?? point.CoverImageSource;
						point.Creator = GetConfigValue(element.Element("Creator")) ?? point.Creator;
						DateTime date = new DateTime();
						if (DateTime.TryParseExact(GetConfigValue(element.Element("CreationDate")), "yyyy.MM.dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
						{ 
							point.StartDate = date; 
						}
					}
				}

				this.items.Add(point);
			}
		}
	}
}
